// Copyrights by Kenneth Lee, 2022. All Rights Reserved

#ifndef __VALUE_HPP__
#define __VALUE_HPP__

#include <iostream>
#include <assert.h>

using namespace std;

#ifdef USE_FLOAT_VAL
# define Val FloatVal
# include "float_val.hpp"
#else
# define Val AnaVal
# include "ana_val.hpp"
#endif

class ValComp {
private:
	const static bool show_id = false; // for debug id allocation

	bool contain_id(int id);
	void clone_parent(ValComp *n);
public:
	enum OPS { ADD, SUB, MUL, DIV, INV_OP };

	Val ret;	// evaluate result, NULL also means "NOT SET"
	Val* vals;
	int* ids;	// indexes of value in splited ValComp, temporal used by emulation algorithm
	int size;
	OPS op;
	ValComp *left, *right, *parent;

	ValComp();
	ValComp(int sz);
	ValComp(ValComp *src, ValComp *sub);
	ValComp(int argc, char *argv[]);
	ValComp * clone() const;
	ValComp * clone_tree();
	friend ostream & show(ostream & os, const ValComp & vg, int i);
	friend ostream & operator<<(ostream & os, const ValComp & vc);
	bool is_right_most();
	void copy_by_id(ValComp *vc, int tgt_id, int src_id);
	void merge_op(ValComp *l, ValComp *r, OPS o);
	ValComp *find_root();
	void evaluate(void);
	void show_expr(void);
};

extern void free_tree(ValComp *root);
extern ValComp *find_unsolved_leaf(ValComp *r);
extern ostream & operator<<(ostream & os, const ValComp::OPS & op);

#endif
